﻿//////////////////////////////////////////////////////////////////////////////
//
// Copyright © 1998-2024 Glodon Company Limited.
//
// Licensed under the MIT License
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the “Software”),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
//////////////////////////////////////////////////////////////////////////////
#include "FamMEPTemplateUtility.h"
#include "IDocument.h"
#include "IFamilyManager.h"
#include "FamStructureTemplateUtility.h"
#include "IParameterValueDouble.h"
#include "IFamilyReferenceLine.h"
#include "IModelView.h"
#include "GbmpModelViewUtil.h"
#include "FamilyConstraintUtils.h"
#include "IFamilyMultiDistanceDimension.h"
#include "IFamilyDistanceRatioConstraint.h"
#include "IFamilyAngleConstraint.h"
#include "GcmpBuiltInCategoryUniIdentities.h"
#include "ReferencePlaneUtils.h"
#include "UnitUniIdentities.h"
#include "ParameterType.h"
#include "IFamilyParameterDefinition.h"
#include "IGraphicsNodeReference.h"
#include "IElementBasicInformation.h"
#include "IReferencePlane.h"
#include "IFamilyDistanceConstraint.h"
#include "FamilyConstraintReferenceType.h"
#include "IGraphicsCurve3d.h"
#include "FamilySolverUtils.h"
#include "FamilySolverResult.h"

#include "EnableCompileWarning_The_LAST_IncludeInCpp.h"

using namespace gcmp;
using namespace gfam;


void gfam::FamMEPTemplateUtility::InitTeeFamilyDocument(gcmp::IDocument* pDoc)
{
    DBG_WARN_AND_RETURN_VOID_UNLESS(pDoc != nullptr, L"pDoc为空",L"GDMPLab",L"2024-03-30");

    IFamilyManager* pFamilyManager = IFamilyManager::Get(pDoc);
    DBG_WARN_AND_RETURN_VOID_UNLESS(pFamilyManager != nullptr, L"pFamilyManager为空",L"GDMPLab",L"2024-03-30");
    pFamilyManager->GetBasicInformation()->SetName(MEP_TEE_TEMPLATE_NAME);

    //////////////////////////////////////////////////////////////////////////
    // 三通件的族参数
    TeeParametersValue paramsValue;
    std::vector<IFamilyParameterDefinition*> newParamDefs;
    AddTeeLengthParameters(pFamilyManager, newParamDefs, paramsValue);
    // L"内衬厚度"
    // L"隔热层厚度"
    AddMEPThicknessParameter(pFamilyManager);

    std::vector<IReferencePlane *> newRefPlanes;
    std::vector<IFamilyReferenceLine*> newRefLines;
    CreateTeeTemplate(pDoc, newRefPlanes, newRefLines, paramsValue.length_1, paramsValue.length_3);

    IModelView* pModelView = GbmpModelViewUtil::FindViewByBuiltinIndex(pDoc, BMVI_BaseLevel);
    DBG_WARN_AND_RETURN_VOID_UNLESS(pModelView != nullptr, L"无法获得ModelView",L"GDMPLab",L"2024-03-30");
    IReferencePlane * frontBackPlane = GetReferencePlane(pDoc, ProjectReferenceTypeOfReferencePlane::CenterOfFrontBack);;
    DBG_WARN_AND_RETURN_VOID_UNLESS(frontBackPlane, L"获取不到参照平面! ",L"GDMPLab",L"2024-03-30");

    Vector3d dimPosition1(-1200, 0, 0);
    IFamilyMultiDistanceDimension* pDim = nullptr;
    IFamilyDistanceConstraint* pDistanceConstraint1 = FamStructureTemplateUtility::CreateDistanceConstraint(pDoc, dimPosition1, FamilyTemplateConst::DimScale
        , GbmpModelViewUtil::GetWorkPlaneCoordinate(pModelView), newRefPlanes.at(2)->GetElementId(), gcmp::GraphicsNodeReferenceType::GraphicsNodeSelf, gcmp::GraphicsNodeId(1)
        , frontBackPlane->GetElementId(), gcmp::GraphicsNodeReferenceType::GraphicsNodeSelf, gcmp::GraphicsNodeId(1), pDim);
    DBG_WARN_AND_RETURN_VOID_UNLESS(pDistanceConstraint1, L"距离约束创建失败! ",L"GDMPLab",L"2024-03-30");
    pDistanceConstraint1->CalcDimValue();
    pDistanceConstraint1->SetFamilyParameterDefinitionId(newParamDefs.at(2)->GetElementId());

    //////////////////////////////////////////////////////////////////////////
    // 参照线几何约束
    OwnerPtr<IGraphicsCurve3d> opCurve0 = newRefLines.at(0)->GetCurve();
    OwnerPtr<IGraphicsCurve3d> opCurve1 = newRefLines.at(1)->GetCurve();
    OwnerPtr<IGraphicsCurve3d> opCurve2 = newRefLines.at(2)->GetCurve();
    DBG_WARN_AND_RETURN_VOID_UNLESS(opCurve0 && opCurve1 && opCurve2, L"参照线的几何曲线不存在",L"GDMPLab",L"2024-03-30");

    Coordinate3d workPlaneCoord = GbmpModelViewUtil::GetWorkPlaneCoordinate(pModelView);
    FamilyConstraintUtils::AddCoincidentConstraintOutOfSketch(pDoc,
        workPlaneCoord,
        newRefLines.at(0)->GetOwnerElement()->GetBasicInformation()->GetElementId(), FamilyConstraintReferenceType::Start, opCurve0->GetId(),
        newRefLines.at(2)->GetOwnerElement()->GetBasicInformation()->GetElementId(), FamilyConstraintReferenceType::Start, opCurve2->GetId());

    FamilyConstraintUtils::AddCoincidentConstraintOutOfSketch(pDoc,
        workPlaneCoord,
        newRefLines.at(1)->GetOwnerElement()->GetBasicInformation()->GetElementId(), FamilyConstraintReferenceType::Start, opCurve1->GetId(),
        newRefLines.at(2)->GetOwnerElement()->GetBasicInformation()->GetElementId(), FamilyConstraintReferenceType::Start, opCurve2->GetId());

    FamilySolverResult ret = FamilySolverUtils::SolveDocument(pDoc);
    DBG_WARN_AND_RETURN_VOID_UNLESS(ret == FamilySolverResult::Ok, L"解算失败! ",L"GDMPLab",L"2024-03-30");
}

void FamMEPTemplateUtility::AddTeeLengthParameters(IFamilyManager* pFamilyManager, std::vector<IFamilyParameterDefinition*>& newParamDefs, const TeeParametersValue& paramsValue)
{
    // L"肩部"
    IFamilyParameterDefinition* pShoulderLengthParam = AddFamilyParameter(pFamilyManager, GBMP_TR(L"肩部"), paramsValue.shoulderLength, UNIT(Length), false, L"");
    DBG_WARN_AND_RETURN_VOID_UNLESS(pShoulderLengthParam, L"创建三通构件“肩部”参数不成功",L"GDMPLab",L"2024-03-30");
    newParamDefs.push_back(pShoulderLengthParam);

    // L"长度3a"
    IFamilyParameterDefinition* pLength_3aParam = AddFamilyParameter(pFamilyManager, GBMP_TR(L"长度3a"), paramsValue.length_3a, UNIT(Length), false, L"");
    DBG_WARN_AND_RETURN_VOID_UNLESS(pLength_3aParam, L"创建三通构件“长度3a”参数不成功",L"GDMPLab",L"2024-03-30");
    newParamDefs.push_back(pLength_3aParam);

    // L"长度3"
    const std::wstring length_3Formula = pLength_3aParam->GetBasicInformation()->GetName() + L"+" + pShoulderLengthParam->GetBasicInformation()->GetName();
    std::wstring strLength_3Name = StringUtil::FormatWString(GBMP_TR(L"长度3"));
    IFamilyParameterDefinition* pLength_3Param = AddFamilyParameter(pFamilyManager, strLength_3Name, paramsValue.length_3, UNIT(Length), true, length_3Formula);
    DBG_WARN_AND_RETURN_VOID_UNLESS(pLength_3Param, L"创建三通构件“长度3”参数不成功",L"GDMPLab",L"2024-03-30");
    newParamDefs.push_back(pLength_3Param);

    // L"长度1a"
    IFamilyParameterDefinition* pLength_1aParam = AddFamilyParameter(pFamilyManager, GBMP_TR(L"长度1a"), paramsValue.length_1a, UNIT(Length), false, L"");
    DBG_WARN_AND_RETURN_VOID_UNLESS(pLength_1aParam, L"创建三通构件“长度1a”参数不成功",L"GDMPLab",L"2024-03-30");
    newParamDefs.push_back(pLength_1aParam);

    // L"长度1"
    const std::wstring length_1Formula = pLength_1aParam->GetBasicInformation()->GetName() + L"+" + pShoulderLengthParam->GetBasicInformation()->GetName();
    std::wstring strLength_1Name = StringUtil::FormatWString(GBMP_TR(L"长度1"));
    IFamilyParameterDefinition* pLength_1Param = AddFamilyParameter(pFamilyManager, strLength_1Name, paramsValue.length_1, UNIT(Length), true, length_1Formula);
    DBG_WARN_AND_RETURN_VOID_UNLESS(pLength_1Param, L"创建“长度1”参数不成功",L"GDMPLab",L"2024-03-30");
    newParamDefs.push_back(pLength_1Param);
}

void gfam::FamMEPTemplateUtility::InitCrossFamilyDocument(gcmp::IDocument* pDoc)
{
    IFamilyManager* pFamilyManager = IFamilyManager::Get(pDoc);
    DBG_WARN_AND_RETURN_VOID_UNLESS(pFamilyManager != nullptr, L"pFamilyManager为空",L"GDMPLab",L"2024-03-30");
    pFamilyManager->GetBasicInformation()->SetName(MEP_CROSS_TEMPLATE_NAME);

    //////////////////////////////////////////////////////////////////////////
    // 族参数
    CrossParametersValue paramsValue;
    std::vector<IFamilyParameterDefinition*> newParamDefs;
    AddCrossLengthParameters(pFamilyManager, newParamDefs, paramsValue);

    // L"内衬厚度"
    // L"隔热层厚度"
    AddMEPThicknessParameter(pFamilyManager);

    std::vector<IReferencePlane *> newRefPlanes;
    std::vector<IFamilyReferenceLine*> newRefLines;
    CreateTeeTemplate(pDoc, newRefPlanes, newRefLines, paramsValue.length_1, paramsValue.length_3);

    //////////////////////////////////////////////////////////////////////////
    // 参照线，平面视图下
    //        3|
    //    0____|____1
    //         |
    //         |2
    IModelView* pModelView = GbmpModelViewUtil::FindViewByBuiltinIndex(pDoc, BMVI_BaseLevel);
    DBG_WARN_AND_RETURN_VOID_UNLESS(pModelView != nullptr, L"无法获得ModelView",L"GDMPLab",L"2024-03-30");
    ElementId workPlaneId = GbmpModelViewUtil::GetReferencePlaneIdOfWorkPlane(pModelView);
    Vector3d lineEndPt = Vector3d(0, paramsValue.length_3, 0);
    IFamilyReferenceLine* pLine3 = IFamilyReferenceLine::CreateAsStraightLine(pDoc, workPlaneId, Vector3d::Zero, lineEndPt);
    pLine3->SetReferenceLineType(ReferenceLineTypes::BuildInReferenceLineType);
    Coordinate3d workPlaneCoord = GbmpModelViewUtil::GetWorkPlaneCoordinate(pModelView);

    AddCrossReferenceLineConstraint(pDoc, newRefLines, pLine3, workPlaneCoord);
    IReferencePlane * pUpReferencePlane = CreateCrossReferencePlane(pDoc);
    // 前后中心面，左右中心面
    IReferencePlane * pFrontBackCenterPlane = GetReferencePlane(pDoc, ProjectReferenceTypeOfReferencePlane::CenterOfFrontBack);
    IReferencePlane * pLeftRightCenterPlane = GetReferencePlane(pDoc, ProjectReferenceTypeOfReferencePlane::CenterOfLeftRight);

    DBG_WARN_AND_RETURN_VOID_UNLESS(pFrontBackCenterPlane&&pLeftRightCenterPlane, L"获取不到参照平面! ",L"GDMPLab",L"2024-03-30");
    OwnerPtr<IGraphicsNodeReference> leftRightGNodeRef = IGraphicsNodeReference::Create(pLeftRightCenterPlane->GetBasicInformation()->GetElementId(), GraphicsNodeId(1));
    OwnerPtr<IGraphicsNodeReference> line3GNodeRef = IGraphicsNodeReference::Create(pLine3->GetOwnerElement()->GetBasicInformation()->GetElementId(), GraphicsNodeId(0));
    FamilyConstraintUtils::AddGeometryConstraint(pDoc, FamilyConstraintType::AlignGeometry,
        *leftRightGNodeRef, *line3GNodeRef, ElementId::InvalidID, ElementId::InvalidID, workPlaneCoord);

    OwnerPtr<IGraphicsNodeReference> upPlaneGNodeRef = IGraphicsNodeReference::Create(pUpReferencePlane->GetBasicInformation()->GetElementId(), GraphicsNodeId(1));
    line3GNodeRef->SetGraphicsNodeReferenceType(GraphicsNodeReferenceType::EndPoint);
    FamilyConstraintUtils::AddGeometryConstraint(pDoc, FamilyConstraintType::AlignGeometry,
        *upPlaneGNodeRef, *line3GNodeRef, ElementId::InvalidID, ElementId::InvalidID, workPlaneCoord);

    //////////////////////////////////////////////////////////////////////////
    // 相等约束
    Vector3d dimPositionEqual(-1200, 0, 0);
    IFamilyMultiDistanceDimension*pDimEqual = IFamilyMultiDistanceDimension::Create(pDoc, dimPositionEqual, FamilyTemplateConst::DimScale, ElementId(), ElementId(), workPlaneCoord, true);
    gcmp::OwnerPtr<IGraphicsNodeReference> opRef1 = IGraphicsNodeReference::Create(newRefPlanes.at(2)->GetBasicInformation()->GetElementId(), GraphicsNodeId(1));
    pDimEqual->AddReferenceObject(TransferOwnership(opRef1));
    gcmp::OwnerPtr<IGraphicsNodeReference> opRef2 = IGraphicsNodeReference::Create(pFrontBackCenterPlane->GetBasicInformation()->GetElementId(), GraphicsNodeId(1));
    pDimEqual->AddReferenceObject(TransferOwnership(opRef2));
    gcmp::OwnerPtr<IGraphicsNodeReference> opRef3 = IGraphicsNodeReference::Create(pUpReferencePlane->GetBasicInformation()->GetElementId(), GraphicsNodeId(1));
    pDimEqual->AddReferenceObject(TransferOwnership(opRef3));

    IFamilyDistanceRatioConstraint* pEqualConstraint = IFamilyDistanceRatioConstraint::Create(pDoc, ElementId(), ElementId(), pDimEqual->GetOwnerElementId(), workPlaneCoord);
    gcmp::OwnerPtr<IGraphicsNodeReference> opRef5 = IGraphicsNodeReference::Create(newRefPlanes.at(2)->GetBasicInformation()->GetElementId(), GraphicsNodeId(1));
    pEqualConstraint->AddReferenceObject(TransferOwnership(opRef5));
    gcmp::OwnerPtr<IGraphicsNodeReference> opRef6 = IGraphicsNodeReference::Create(pFrontBackCenterPlane->GetBasicInformation()->GetElementId(), GraphicsNodeId(1));
    pEqualConstraint->AddReferenceObject(TransferOwnership(opRef6));
    gcmp::OwnerPtr<IGraphicsNodeReference> opRef7 = IGraphicsNodeReference::Create(pUpReferencePlane->GetBasicInformation()->GetElementId(), GraphicsNodeId(1));
    pEqualConstraint->AddReferenceObject(TransferOwnership(opRef7));
    pEqualConstraint->SetRatioValue(0.5);
    pDimEqual->AddConstraintObject(pEqualConstraint->GetOwnerElementId());

    // 距离约束
    Vector3d dimPosition(-1500, 0, 0);
    IFamilyMultiDistanceDimension* pDim = nullptr;
    IFamilyDistanceConstraint* pDistanceConstraint = FamStructureTemplateUtility::CreateDistanceConstraint(pDoc, dimPosition, FamilyTemplateConst::DimScale
        , workPlaneCoord, pUpReferencePlane->GetElementId(), gcmp::GraphicsNodeReferenceType::GraphicsNodeSelf, gcmp::GraphicsNodeId(1)
        , pFrontBackCenterPlane->GetElementId(), gcmp::GraphicsNodeReferenceType::GraphicsNodeSelf, gcmp::GraphicsNodeId(1), pDim);
    DBG_WARN_AND_RETURN_VOID_UNLESS(pDistanceConstraint, L"距离约束创建失败! ",L"GDMPLab",L"2024-03-30");
    pDistanceConstraint->CalcDimValue();
    pDistanceConstraint->SetFamilyParameterDefinitionId(newParamDefs.at(1)->GetElementId());

    FamilySolverResult ret = FamilySolverUtils::SolveDocument(pDoc);
    DBG_WARN_AND_RETURN_VOID_UNLESS(ret == FamilySolverResult::Ok, L"解算失败! ",L"GDMPLab",L"2024-03-30");
}

void FamMEPTemplateUtility::AddCrossLengthParameters(gfam::IFamilyManager* pFamilyManager, std::vector<gfam::IFamilyParameterDefinition *>& newParamDefs, const CrossParametersValue& paramsValue)
{
    IFamilyParameterDefinition* pShoulderLengthParam = AddFamilyParameter(pFamilyManager, GBMP_TR(L"肩部"), paramsValue.shoulderLength, UNIT(Length), false, L"");
    DBG_WARN_AND_RETURN_VOID_UNLESS(pShoulderLengthParam, L"创建“肩部”参数不成功",L"GDMPLab",L"2024-03-30");
    newParamDefs.push_back(pShoulderLengthParam);

    // L"长度3"
    IFamilyParameterDefinition* pLength_3Param = AddFamilyParameter(pFamilyManager, GBMP_TR(L"长度3"), paramsValue.length_3, UNIT(Length), false, L"");
    DBG_WARN_AND_RETURN_VOID_UNLESS(pLength_3Param, L"创建“长度3”参数不成功",L"GDMPLab",L"2024-03-30");
    newParamDefs.push_back(pLength_3Param);

    // L"长度1"
    IFamilyParameterDefinition* pLength_1Param = AddFamilyParameter(pFamilyManager, GBMP_TR(L"长度1"), paramsValue.length_1, UNIT(Length), false, L"");
    DBG_WARN_AND_RETURN_VOID_UNLESS(pLength_1Param, L"创建“长度1”参数不成功",L"GDMPLab",L"2024-03-30");
    newParamDefs.push_back(pLength_1Param);
}
void FamMEPTemplateUtility::AddCrossReferenceLineConstraint(gcmp::IDocument* pDoc,
    const std::vector<IFamilyReferenceLine *>& newRefLines,
    const IFamilyReferenceLine* pLine3, 
    const Coordinate3d& workPlaneCoord)
{
    OwnerPtr<IGraphicsCurve3d> opCurve0 = newRefLines.at(0)->GetCurve();
    OwnerPtr<IGraphicsCurve3d> opCurve1 = newRefLines.at(1)->GetCurve();
    OwnerPtr<IGraphicsCurve3d> opCurve2 = newRefLines.at(2)->GetCurve();
    OwnerPtr<IGraphicsCurve3d> opCurve3 = pLine3->GetCurve();
    DBG_WARN_AND_RETURN_VOID_UNLESS(opCurve0 && opCurve1 && opCurve2 && opCurve3, L"参照线的几何曲线不存在",L"GDMPLab",L"2024-03-30");
    // 参照线的共点约束
    FamilyConstraintUtils::AddCoincidentConstraintOutOfSketch(pDoc,
        workPlaneCoord,
        newRefLines.at(0)->GetOwnerElement()->GetBasicInformation()->GetElementId(), FamilyConstraintReferenceType::Start, opCurve0->GetId(),
        newRefLines.at(2)->GetOwnerElement()->GetBasicInformation()->GetElementId(), FamilyConstraintReferenceType::Start, opCurve2->GetId());

    FamilyConstraintUtils::AddCoincidentConstraintOutOfSketch(pDoc,
        workPlaneCoord,
        newRefLines.at(1)->GetOwnerElement()->GetBasicInformation()->GetElementId(), FamilyConstraintReferenceType::Start, opCurve1->GetId(),
        pLine3->GetOwnerElement()->GetBasicInformation()->GetElementId(), FamilyConstraintReferenceType::Start, opCurve3->GetId());
}
IReferencePlane * FamMEPTemplateUtility::CreateCrossReferencePlane(gcmp::IDocument* pDoc)
{
    CrossParametersValue paramsValue;
    const double lengthU = 3600;
    const double lengthV = 4500;
    Vector3d startPtZ = Vector3d(-lengthU*0.5, paramsValue.length_3, 0);
    Vector3d endPtZ = Vector3d(lengthU*0.5, paramsValue.length_3, 0);
    IReferencePlane * pUpReferencePlane = ReferencePlaneUtils::CreateByPoints(pDoc, startPtZ, endPtZ, Vector3d::UnitZ);
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pUpReferencePlane != nullptr, L"创建参照平面失败",L"GDMPLab",L"2024-03-30");
    pUpReferencePlane->GetBasicInformation()->SetName(GBMP_TR(L"参照平面"));
    pUpReferencePlane->SetVisibleUVMin(Vector2d(-lengthU*0.5, -lengthV*0.5));
    pUpReferencePlane->SetVisibleUVMax(Vector2d(lengthU*0.5, lengthV*0.5));

    return pUpReferencePlane;
}

void gfam::FamMEPTemplateUtility::CreateTeeTemplate(IDocument* pDoc,
    std::vector<IReferencePlane *>& newRefPlanes,
    std::vector<IFamilyReferenceLine*>& newRefLines,
    double length_1, double length_3)
{
    IFamilyManager* pFamilyManager = IFamilyManager::Get(pDoc);
    DBG_WARN_AND_RETURN_VOID_UNLESS(pFamilyManager != nullptr, L"pFamilyManager为空",L"GDMPLab",L"2024-03-30");

    //////////////////////////////////////////////////////////////////////////
    // 参照平面
    CreateTeeReferencePlane(pDoc, newRefPlanes);

    //////////////////////////////////////////////////////////////////////////
    // 参照线，平面视图下
    //    0____ ____1
    //         |
    //         |2
    IModelView* pModelView = GbmpModelViewUtil::FindViewByBuiltinIndex(pDoc, BMVI_BaseLevel);
    DBG_WARN_AND_RETURN_VOID_UNLESS(pModelView != nullptr, L"无法获得ModelView",L"GDMPLab",L"2024-03-30");
    ElementId workPlaneId = GbmpModelViewUtil::GetReferencePlaneIdOfWorkPlane(pModelView);
    CreateTeeReferenceLine(pDoc, newRefLines, workPlaneId);

    // 前后中心面，左右中心面 
    IReferencePlane * frontBackPlane = GetReferencePlane(pDoc, ProjectReferenceTypeOfReferencePlane::CenterOfFrontBack);
    IReferencePlane * leftRightPlane = GetReferencePlane(pDoc, ProjectReferenceTypeOfReferencePlane::CenterOfLeftRight);
    DBG_WARN_AND_RETURN_VOID_UNLESS(frontBackPlane&&leftRightPlane, L"获取不到参照平面! ",L"GDMPLab",L"2024-03-30");

    Coordinate3d workPlaneCoord = GbmpModelViewUtil::GetWorkPlaneCoordinate(pModelView);
    AddTeeReferenceLineConstraint(pDoc, newRefPlanes, newRefLines, workPlaneCoord);

    //////////////////////////////////////////////////////////////////////////
    // 距离约束
    Vector3d dimPositionEqual(0, 1200, 0);
    IFamilyMultiDistanceDimension*pDimEqual = IFamilyMultiDistanceDimension::Create(pDoc, dimPositionEqual, FamilyTemplateConst::DimScale, ElementId(), ElementId(), workPlaneCoord, true);
    gcmp::OwnerPtr<IGraphicsNodeReference> opRef1 = IGraphicsNodeReference::Create(newRefPlanes.at(1)->GetBasicInformation()->GetElementId(), GraphicsNodeId(1));
    pDimEqual->AddReferenceObject(TransferOwnership(opRef1));
    gcmp::OwnerPtr<IGraphicsNodeReference> opRef2 = IGraphicsNodeReference::Create(leftRightPlane->GetBasicInformation()->GetElementId(), GraphicsNodeId(1));
    pDimEqual->AddReferenceObject(TransferOwnership(opRef2));
    gcmp::OwnerPtr<IGraphicsNodeReference> opRef3 = IGraphicsNodeReference::Create(newRefPlanes.at(0)->GetBasicInformation()->GetElementId(), GraphicsNodeId(1));
    pDimEqual->AddReferenceObject(TransferOwnership(opRef3));

    IFamilyDistanceRatioConstraint* pEqualConstraint = IFamilyDistanceRatioConstraint::Create(pDoc, ElementId(), ElementId(), pDimEqual->GetOwnerElementId(), workPlaneCoord);
    gcmp::OwnerPtr<IGraphicsNodeReference> opRef5 = IGraphicsNodeReference::Create(newRefPlanes.at(1)->GetBasicInformation()->GetElementId(), GraphicsNodeId(1));
    pEqualConstraint->AddReferenceObject(TransferOwnership(opRef5));
    gcmp::OwnerPtr<IGraphicsNodeReference> opRef6 = IGraphicsNodeReference::Create(leftRightPlane->GetBasicInformation()->GetElementId(), GraphicsNodeId(1));
    pEqualConstraint->AddReferenceObject(TransferOwnership(opRef6));
    gcmp::OwnerPtr<IGraphicsNodeReference> opRef7 = IGraphicsNodeReference::Create(newRefPlanes.at(0)->GetBasicInformation()->GetElementId(), GraphicsNodeId(1));
    pEqualConstraint->AddReferenceObject(TransferOwnership(opRef7));
    pEqualConstraint->SetRatioValue(0.5);
    pDimEqual->AddConstraintObject(pEqualConstraint->GetOwnerElementId());

    Vector3d dimPosition(0, 1500, 0);
    IFamilyMultiDistanceDimension* pDim = nullptr;
    IFamilyDistanceConstraint* pDistanceConstraint = FamStructureTemplateUtility::CreateDistanceConstraint(pDoc, dimPosition, FamilyTemplateConst::DimScale
        , workPlaneCoord, newRefPlanes.at(1)->GetElementId(), gcmp::GraphicsNodeReferenceType::GraphicsNodeSelf, gcmp::GraphicsNodeId(1)
        , leftRightPlane->GetElementId(), gcmp::GraphicsNodeReferenceType::GraphicsNodeSelf, gcmp::GraphicsNodeId(1), pDim);
    DBG_WARN_AND_RETURN_VOID_UNLESS(pDistanceConstraint, L"距离约束创建失败! ",L"GDMPLab",L"2024-03-30");
    pDistanceConstraint->CalcDimValue();
    const IFamilyParameterDefinition* length_1ParamDef = pFamilyManager->GetFamilyParameterDefinition(GBMP_TR(L"长度1"));
    DBG_WARN_AND_RETURN_VOID_UNLESS(length_1ParamDef, L"参数获取不成功",L"GDMPLab",L"2024-03-30");
    pDistanceConstraint->SetFamilyParameterDefinitionId(length_1ParamDef->GetElementId());
}
void FamMEPTemplateUtility::CreateTeeReferencePlane(gcmp::IDocument* pDoc, std::vector<gcmp::IReferencePlane *>& newRefPlanes)
{
    TeeParametersValue paramsValue;

    const double lengthU = 3600;
    const double lengthV = 4500;

    Vector3d startPtZ(paramsValue.length_1, -lengthU*0.5, 0);
    Vector3d endPtZ(paramsValue.length_1, lengthU*0.5, 0);
    IReferencePlane * pRightReferencePlane = ReferencePlaneUtils::CreateByPoints(pDoc, startPtZ, endPtZ, Vector3d::UnitZ);
    DBG_WARN_AND_RETURN_VOID_UNLESS(pRightReferencePlane != nullptr, L"创建参照平面失败",L"GDMPLab",L"2024-03-30");
    pRightReferencePlane->GetBasicInformation()->SetName(GBMP_TR(L"参照平面"));
    pRightReferencePlane->SetVisibleUVMin(Vector2d(-lengthU*0.5, -lengthV*0.5));
    pRightReferencePlane->SetVisibleUVMax(Vector2d(lengthU*0.5, lengthV*0.5));

    startPtZ = Vector3d(-paramsValue.length_1, -lengthU*0.5, 0);
    endPtZ = Vector3d(-paramsValue.length_1, lengthU*0.5, 0);
    IReferencePlane * pLeftReferencePlane = ReferencePlaneUtils::CreateByPoints(pDoc, startPtZ, endPtZ, Vector3d::UnitZ);
    DBG_WARN_AND_RETURN_VOID_UNLESS(pLeftReferencePlane != nullptr, L"创建参照平面失败",L"GDMPLab",L"2024-03-30");
    pLeftReferencePlane->GetBasicInformation()->SetName(GBMP_TR(L"参照平面"));
    pLeftReferencePlane->SetVisibleUVMin(Vector2d(-lengthU*0.5, -lengthV*0.5));
    pLeftReferencePlane->SetVisibleUVMax(Vector2d(lengthU*0.5, lengthV*0.5));

    startPtZ = Vector3d(-lengthU*0.5, -paramsValue.length_3, 0);
    endPtZ = Vector3d(lengthU*0.5, -paramsValue.length_3, 0);
    IReferencePlane * pBottomReferencePlane = ReferencePlaneUtils::CreateByPoints(pDoc, startPtZ, endPtZ, Vector3d::UnitZ);
    DBG_WARN_AND_RETURN_VOID_UNLESS(pBottomReferencePlane != nullptr, L"创建参照平面失败",L"GDMPLab",L"2024-03-30");
    pBottomReferencePlane->GetBasicInformation()->SetName(GBMP_TR(L"参照平面"));
    pBottomReferencePlane->SetVisibleUVMin(Vector2d(-lengthU*0.5, -lengthV*0.5));
    pBottomReferencePlane->SetVisibleUVMax(Vector2d(lengthU*0.5, lengthV*0.5));

    newRefPlanes.push_back(pRightReferencePlane);
    newRefPlanes.push_back(pLeftReferencePlane);
    newRefPlanes.push_back(pBottomReferencePlane);
}
void FamMEPTemplateUtility::CreateTeeReferenceLine(gcmp::IDocument* pDoc, std::vector<IFamilyReferenceLine *>& newRefLines, const ElementId& workPlaneId)
{
    TeeParametersValue paramsValue;

    Vector3d lineEndPt(-paramsValue.length_1, 0, 0);
    IFamilyReferenceLine* pLine0 = IFamilyReferenceLine::CreateAsStraightLine(pDoc, workPlaneId, Vector3d::Zero, lineEndPt);
    lineEndPt = Vector3d(paramsValue.length_1, 0, 0);
    IFamilyReferenceLine* pLine1 = IFamilyReferenceLine::CreateAsStraightLine(pDoc, workPlaneId, Vector3d::Zero, lineEndPt);
    lineEndPt = Vector3d(0, -paramsValue.length_3, 0);
    IFamilyReferenceLine* pLine2 = IFamilyReferenceLine::CreateAsStraightLine(pDoc, workPlaneId, Vector3d::Zero, lineEndPt);
    {// 设为内置参照线，不可删除
        pLine0->SetReferenceLineType(ReferenceLineTypes::BuildInReferenceLineType);
        pLine1->SetReferenceLineType(ReferenceLineTypes::BuildInReferenceLineType);
        pLine2->SetReferenceLineType(ReferenceLineTypes::BuildInReferenceLineType);
    }

    newRefLines.push_back(pLine0);
    newRefLines.push_back(pLine1);
    newRefLines.push_back(pLine2);
}
void FamMEPTemplateUtility::AddTeeReferenceLineConstraint(gcmp::IDocument* pDoc,
    const std::vector<gcmp::IReferencePlane *>& newRefPlanes,
    const std::vector<IFamilyReferenceLine *>& newRefLines,
    const Coordinate3d& workPlaneCoord)
{
    IReferencePlane * frontBackPlane = GetReferencePlane(pDoc, ProjectReferenceTypeOfReferencePlane::CenterOfFrontBack);
    IReferencePlane * leftRightPlane = GetReferencePlane(pDoc, ProjectReferenceTypeOfReferencePlane::CenterOfLeftRight);
    DBG_WARN_AND_RETURN_VOID_UNLESS(frontBackPlane&&leftRightPlane, L"获取不到参照平面! ",L"GDMPLab",L"2024-03-30");

    OwnerPtr<IGraphicsCurve3d> opCurve0 = newRefLines.at(0)->GetCurve();
    OwnerPtr<IGraphicsCurve3d> opCurve1 = newRefLines.at(1)->GetCurve();
    OwnerPtr<IGraphicsCurve3d> opCurve2 = newRefLines.at(2)->GetCurve();
    DBG_WARN_AND_RETURN_VOID_UNLESS(opCurve0 && opCurve1 && opCurve2, L"参照线的几何曲线不存在",L"GDMPLab",L"2024-03-30");

    OwnerPtr<IGraphicsNodeReference> frontBackGNodeRef = IGraphicsNodeReference::Create(frontBackPlane->GetBasicInformation()->GetElementId(), GraphicsNodeId(1));
    OwnerPtr<IGraphicsNodeReference> leftRightGNodeRef = IGraphicsNodeReference::Create(leftRightPlane->GetBasicInformation()->GetElementId(), GraphicsNodeId(1));
    OwnerPtr<IGraphicsNodeReference> line0GNodeRef = IGraphicsNodeReference::Create(newRefLines.at(0)->GetOwnerElement()->GetBasicInformation()->GetElementId(), opCurve0->GetId());
    OwnerPtr<IGraphicsNodeReference> line1GNodeRef = IGraphicsNodeReference::Create(newRefLines.at(1)->GetOwnerElement()->GetBasicInformation()->GetElementId(), opCurve1->GetId());
    OwnerPtr<IGraphicsNodeReference> line2GNodeRef = IGraphicsNodeReference::Create(newRefLines.at(2)->GetOwnerElement()->GetBasicInformation()->GetElementId(), opCurve2->GetId());
    FamilyConstraintUtils::AddGeometryConstraint(pDoc, FamilyConstraintType::AlignGeometry,
        *frontBackGNodeRef, *line0GNodeRef, ElementId::InvalidID, ElementId::InvalidID, workPlaneCoord);
    FamilyConstraintUtils::AddGeometryConstraint(pDoc, FamilyConstraintType::AlignGeometry,
        *frontBackGNodeRef, *line1GNodeRef, ElementId::InvalidID, ElementId::InvalidID, workPlaneCoord);
    FamilyConstraintUtils::AddGeometryConstraint(pDoc, FamilyConstraintType::AlignGeometry,
        *leftRightGNodeRef, *line2GNodeRef, ElementId::InvalidID, ElementId::InvalidID, workPlaneCoord);

    OwnerPtr<IGraphicsNodeReference> leftPlaneGNodeRef = IGraphicsNodeReference::Create(newRefPlanes.at(1)->GetBasicInformation()->GetElementId(), GraphicsNodeId(1));
    OwnerPtr<IGraphicsNodeReference> rightPlaneGNodeRef = IGraphicsNodeReference::Create(newRefPlanes.at(0)->GetBasicInformation()->GetElementId(), GraphicsNodeId(1));
    OwnerPtr<IGraphicsNodeReference> bottomPlaneGNodeRef = IGraphicsNodeReference::Create(newRefPlanes.at(2)->GetBasicInformation()->GetElementId(), GraphicsNodeId(1));
    line0GNodeRef->SetGraphicsNodeReferenceType(GraphicsNodeReferenceType::EndPoint);
    line1GNodeRef->SetGraphicsNodeReferenceType(GraphicsNodeReferenceType::EndPoint);
    line2GNodeRef->SetGraphicsNodeReferenceType(GraphicsNodeReferenceType::EndPoint);
    FamilyConstraintUtils::AddGeometryConstraint(pDoc, FamilyConstraintType::AlignGeometry,
        *leftPlaneGNodeRef, *line0GNodeRef, ElementId::InvalidID, ElementId::InvalidID, workPlaneCoord);
    FamilyConstraintUtils::AddGeometryConstraint(pDoc, FamilyConstraintType::AlignGeometry,
        *rightPlaneGNodeRef, *line1GNodeRef, ElementId::InvalidID, ElementId::InvalidID, workPlaneCoord);
    FamilyConstraintUtils::AddGeometryConstraint(pDoc, FamilyConstraintType::AlignGeometry,
        *bottomPlaneGNodeRef, *line2GNodeRef, ElementId::InvalidID, ElementId::InvalidID, workPlaneCoord);
}

void gfam::FamMEPTemplateUtility::InitElbowFamilyDocument(gcmp::IDocument* pDoc)
{
    IFamilyManager* pFamilyManager = IFamilyManager::Get(pDoc);
    DBG_WARN_AND_RETURN_VOID_UNLESS(pFamilyManager != nullptr, L"pFamilyManager为空",L"GDMPLab",L"2024-03-30");
    pFamilyManager->GetBasicInformation()->SetName(MEP_ELBOW_TEMPLATE_NAME);

    //////////////////////////////////////////////////////////////////////////
    // 族参数
    ElbowParametersValue paramsValue;
    std::vector<IFamilyParameterDefinition*> newParamDefs;
    AddElbowLengthParameters(pFamilyManager, newParamDefs, paramsValue);
    AddMEPThicknessParameter(pFamilyManager);   // L"内衬厚度", L"隔热层厚度"

    //////////////////////////////////////////////////////////////////////////
    // 参照平面
    const double lengthU = 3600;
    const double lengthV = 4500;
    Vector3d startPtZ = Vector3d(-paramsValue.length_1, -lengthU*0.5, 0);
    Vector3d endPtZ = Vector3d(-paramsValue.length_1, lengthU*0.5, 0);
    IReferencePlane * pLeftReferencePlane = ReferencePlaneUtils::CreateByPoints(pDoc, startPtZ, endPtZ, Vector3d::UnitZ);
    DBG_WARN_AND_RETURN_VOID_UNLESS(pLeftReferencePlane != nullptr, L"创建参照平面失败",L"GDMPLab",L"2024-03-30");
    pLeftReferencePlane->GetBasicInformation()->SetName(GBMP_TR(L"参照平面"));
    pLeftReferencePlane->SetVisibleUVMin(Vector2d(-lengthU*0.5, -lengthV*0.5));
    pLeftReferencePlane->SetVisibleUVMax(Vector2d(lengthU*0.5, lengthV*0.5));

    startPtZ = Vector3d(-lengthU*0.5, paramsValue.radius, 0);
    endPtZ = Vector3d(lengthU*0.5, paramsValue.radius, 0);
    IReferencePlane * pUpReferencePlane = ReferencePlaneUtils::CreateByPoints(pDoc, startPtZ, endPtZ, Vector3d::UnitZ);
    DBG_WARN_AND_RETURN_VOID_UNLESS(pUpReferencePlane != nullptr, L"创建参照平面失败",L"GDMPLab",L"2024-03-30");
    pUpReferencePlane->GetBasicInformation()->SetName(GBMP_TR(L"参照平面"));
    pUpReferencePlane->SetVisibleUVMin(Vector2d(-lengthU*0.5, -lengthV*0.5));
    pUpReferencePlane->SetVisibleUVMax(Vector2d(lengthU*0.5, lengthV*0.5));

    // 参照平面添加距离约束
    // 前后中心面，左右中心面
    IReferencePlane * pFrontBackCenterPlane = GetReferencePlane(pDoc, ProjectReferenceTypeOfReferencePlane::CenterOfFrontBack);
    IReferencePlane * pLeftRightCenterPlane = GetReferencePlane(pDoc, ProjectReferenceTypeOfReferencePlane::CenterOfLeftRight);
    DBG_WARN_AND_RETURN_VOID_UNLESS(pFrontBackCenterPlane&&pLeftRightCenterPlane, L"获取不到参照平面! ",L"GDMPLab",L"2024-03-30");

    IModelView* pModelView = GbmpModelViewUtil::FindViewByBuiltinIndex(pDoc, BMVI_BaseLevel);
    DBG_WARN_AND_RETURN_VOID_UNLESS(pModelView != nullptr, L"无法获得ModelView",L"GDMPLab",L"2024-03-30");
    Coordinate3d workPlaneCoord = GbmpModelViewUtil::GetWorkPlaneCoordinate(pModelView);

    Vector3d dimPosition(-1200, 0, 0);
    IFamilyMultiDistanceDimension* pDim = nullptr;
    IFamilyDistanceConstraint* pDistanceConstraint0 = FamStructureTemplateUtility::CreateDistanceConstraint(pDoc, dimPosition, FamilyTemplateConst::DimScale
        , workPlaneCoord, pFrontBackCenterPlane->GetBasicInformation()->GetElementId(), gcmp::GraphicsNodeReferenceType::GraphicsNodeSelf, gcmp::GraphicsNodeId(1)
        , pUpReferencePlane->GetBasicInformation()->GetElementId(), gcmp::GraphicsNodeReferenceType::GraphicsNodeSelf, gcmp::GraphicsNodeId(1), pDim);
    DBG_WARN_AND_RETURN_VOID_UNLESS(pDistanceConstraint0, L"距离约束创建失败! ",L"GDMPLab",L"2024-03-30");
    pDistanceConstraint0->CalcDimValue();
    pDistanceConstraint0->SetFamilyParameterDefinitionId(newParamDefs.at(0)->GetElementId());

    dimPosition = Vector3d(0, 1200, 0);
    IFamilyDistanceConstraint* pDistanceConstraint1 = FamStructureTemplateUtility::CreateDistanceConstraint(pDoc, dimPosition, FamilyTemplateConst::DimScale
        , workPlaneCoord, pLeftRightCenterPlane->GetBasicInformation()->GetElementId(), gcmp::GraphicsNodeReferenceType::GraphicsNodeSelf, gcmp::GraphicsNodeId(1)
        , pLeftReferencePlane->GetBasicInformation()->GetElementId(), gcmp::GraphicsNodeReferenceType::GraphicsNodeSelf, gcmp::GraphicsNodeId(1), pDim);
    DBG_WARN_AND_RETURN_VOID_UNLESS(pDistanceConstraint1, L"距离约束创建失败! ",L"GDMPLab",L"2024-03-30");
    pDistanceConstraint1->CalcDimValue();
    pDistanceConstraint1->SetFamilyParameterDefinitionId(newParamDefs.at(2)->GetElementId());

    std::vector<IFamilyReferenceLine*> newRefLines;
    CreateElbowReferenceLine(pDoc, newRefLines, pModelView);

    // 直线、参照平面对齐约束
    OwnerPtr<IGraphicsNodeReference> line0GNodeRef = IGraphicsNodeReference::Create(newRefLines.at(0)->GetOwnerElement()->GetBasicInformation()->GetElementId(), newRefLines.at(0)->GetCurve()->GetId());
    OwnerPtr<IGraphicsNodeReference> line1GNodeRef = IGraphicsNodeReference::Create(newRefLines.at(1)->GetOwnerElement()->GetBasicInformation()->GetElementId(), newRefLines.at(1)->GetCurve()->GetId());
    OwnerPtr<IGraphicsNodeReference> leftPlaneGNodeRef = IGraphicsNodeReference::Create(pLeftReferencePlane->GetBasicInformation()->GetElementId(), GraphicsNodeId(1));
    OwnerPtr<IGraphicsNodeReference> frontBackPlaneGNodeRef = IGraphicsNodeReference::Create(pFrontBackCenterPlane->GetBasicInformation()->GetElementId(), GraphicsNodeId(1));
    FamilyConstraintUtils::AddGeometryConstraint(pDoc, FamilyConstraintType::AlignGeometry,
        *leftPlaneGNodeRef, *line0GNodeRef, ElementId::InvalidID, ElementId::InvalidID, workPlaneCoord);
    FamilyConstraintUtils::AddGeometryConstraint(pDoc, FamilyConstraintType::AlignGeometry,
        *frontBackPlaneGNodeRef, *line1GNodeRef, ElementId::InvalidID, ElementId::InvalidID, workPlaneCoord);

    line0GNodeRef->SetGraphicsNodeReferenceType(GraphicsNodeReferenceType::StartPoint);
    OwnerPtr<IGraphicsNodeReference> upPlaneGNodeRef = IGraphicsNodeReference::Create(pUpReferencePlane->GetBasicInformation()->GetElementId(), GraphicsNodeId(1));
    FamilyConstraintUtils::AddGeometryConstraint(pDoc, FamilyConstraintType::AlignGeometry,
        *upPlaneGNodeRef, *line0GNodeRef, ElementId::InvalidID, ElementId::InvalidID, workPlaneCoord);

    // 弧形参照线、参照平面对齐约束
    OwnerPtr<IGraphicsNodeReference> arcGNodeRef = IGraphicsNodeReference::Create(newRefLines.at(4)->GetOwnerElement()->GetBasicInformation()->GetElementId(), newRefLines.at(4)->GetCurve()->GetId(), GraphicsNodeReferenceType::CenterPoint);
    FamilyConstraintUtils::AddGeometryConstraint(pDoc, FamilyConstraintType::AlignGeometry,
        *leftPlaneGNodeRef, *arcGNodeRef, ElementId::InvalidID, ElementId::InvalidID, workPlaneCoord);
    FamilyConstraintUtils::AddGeometryConstraint(pDoc, FamilyConstraintType::AlignGeometry,
        *upPlaneGNodeRef, *arcGNodeRef, ElementId::InvalidID, ElementId::InvalidID, workPlaneCoord);

    //////////////////////////////////////////////////////////////////////////
    // 角度约束
    IFamilyAngleConstraint* pAngleConstraint = FamStructureTemplateUtility::CreateAngleConstraint(pDoc, workPlaneCoord
        , newRefLines.at(0)->GetOwnerElement(), gcmp::GraphicsNodeReferenceType::GraphicsNodeSelf, gcmp::GraphicsNodeId(1)
        , newRefLines.at(3)->GetOwnerElement(), gcmp::GraphicsNodeReferenceType::GraphicsNodeSelf, gcmp::GraphicsNodeId(1));
    DBG_WARN_AND_RETURN_VOID_UNLESS(pAngleConstraint, L"角度约束创建失败! ",L"GDMPLab",L"2024-03-30");
    pAngleConstraint->SetRadius(1200);
    pAngleConstraint->SetQuadrant(2);
    pAngleConstraint->SetFamilyParameterDefinitionId(newParamDefs.at(1)->GetElementId());

    FamilySolverResult ret = FamilySolverUtils::SolveDocument(pDoc);
    DBG_WARN_AND_RETURN_VOID_UNLESS(ret == FamilySolverResult::Ok, L"解算失败! ",L"GDMPLab",L"2024-03-30");
}

void FamMEPTemplateUtility::AddElbowLengthParameters(gfam::IFamilyManager* pFM, std::vector<gfam::IFamilyParameterDefinition *>& newParamDefs, const ElbowParametersValue& paramsValue)
{
    // L"中心半径"
    //const double radius = 450;
    std::wstring strRadiusName = StringUtil::FormatWString(GBMP_TR(L"中心半径"));
    IFamilyParameterDefinition* pRadiusParam = AddFamilyParameter(pFM, strRadiusName, paramsValue.radius, UNIT(Length), false, L"");
    DBG_WARN_AND_RETURN_VOID_UNLESS(pRadiusParam, L"创建“中心半径”参数不成功",L"GDMPLab",L"2024-03-30");
    newParamDefs.push_back(pRadiusParam);

    // L"角度"
    //const double angle = 45 * M_PI / 180.0;
    std::wstring strAngleName = StringUtil::FormatWString(GBMP_TR(L"角度"));
    IFamilyParameterDefinition* pAngleParam = AddFamilyParameter(pFM, strAngleName, paramsValue.angle, UNIT(Angle), false, L"");
    DBG_WARN_AND_RETURN_VOID_UNLESS(pAngleParam, L"创建“角度”参数不成功",L"GDMPLab",L"2024-03-30");
    newParamDefs.push_back(pAngleParam);

    // L"长度1"
    const std::wstring length_1Formula = pRadiusParam->GetBasicInformation()->GetName() + L"*tan(" + pAngleParam->GetBasicInformation()->GetName() + L"/2)";
    //const double length_1 = radius * std::tan(angle / 2.0);
    std::wstring strLength_1Name = StringUtil::FormatWString(GBMP_TR(L"长度1"));
    IFamilyParameterDefinition* pLength_1Param = AddFamilyParameter(pFM, strLength_1Name, paramsValue.length_1, UNIT(Length), true, length_1Formula);
    DBG_WARN_AND_RETURN_VOID_UNLESS(pLength_1Param, L"创建“长度1”参数不成功",L"GDMPLab",L"2024-03-30");
    newParamDefs.push_back(pLength_1Param);
}
void FamMEPTemplateUtility::CreateElbowReferenceLine(gcmp::IDocument* pDoc, std::vector<IFamilyReferenceLine *>& newRefLines, const gcmp::IModelView* pModelView)
{
    ElbowParametersValue paramsValue;
    //////////////////////////////////////////////////////////////////////////
    // 参照线
    ElementId workPlaneId = GbmpModelViewUtil::GetReferencePlaneIdOfWorkPlane(pModelView);
    Vector3d lineStartPt(-paramsValue.length_1, 0, 0);
    Vector3d lineEndPt(-paramsValue.length_1, -paramsValue.radius, 0);
    IFamilyReferenceLine* pLine0 = IFamilyReferenceLine::CreateAsStraightLine(pDoc, workPlaneId, lineStartPt, lineEndPt);
    lineStartPt = lineEndPt;
    lineEndPt = Vector3d(0, -paramsValue.radius, 0);
    IFamilyReferenceLine* pLine1 = IFamilyReferenceLine::CreateAsStraightLine(pDoc, workPlaneId, lineStartPt, lineEndPt);
    lineStartPt = lineEndPt;
    double dX = paramsValue.radius * std::cos(paramsValue.angle) - paramsValue.length_1;
    double dY = -paramsValue.radius * std::sin(paramsValue.angle);
    lineEndPt = Vector3d(dX, dY, 0);
    IFamilyReferenceLine* pLine2 = IFamilyReferenceLine::CreateAsStraightLine(pDoc, workPlaneId, lineStartPt, lineEndPt);
    lineStartPt = lineEndPt;
    lineEndPt = Vector3d(-paramsValue.length_1, 0, 0);
    IFamilyReferenceLine* pLine3 = IFamilyReferenceLine::CreateAsStraightLine(pDoc, workPlaneId, lineStartPt, lineEndPt);
    IFamilyReferenceLine* pArc = IFamilyReferenceLine::CreateAsArcByAngle(pDoc, workPlaneId, lineEndPt, paramsValue.radius, Constants::MATH_3PI_2, Constants::MATH_2PI - paramsValue.angle, 1);

    //设置名字    
    pLine0->GetOwnerElement()->GetBasicInformation()->SetName(L"01");
    pLine1->GetOwnerElement()->GetBasicInformation()->SetName(L"02");
    pLine2->GetOwnerElement()->GetBasicInformation()->SetName(L"03");
    pLine3->GetOwnerElement()->GetBasicInformation()->SetName(L"04");
    pArc->GetOwnerElement()->GetBasicInformation()->SetName(L"05");

    {// 设为内置参照线，不可删除
        pLine0->SetReferenceLineType(ReferenceLineTypes::BuildInReferenceLineType);
        pLine1->SetReferenceLineType(ReferenceLineTypes::BuildInReferenceLineType);
        pLine2->SetReferenceLineType(ReferenceLineTypes::BuildInReferenceLineType);
        pLine3->SetReferenceLineType(ReferenceLineTypes::BuildInReferenceLineType);
        pArc->SetReferenceLineType(ReferenceLineTypes::BuildInReferenceLineType);
    }

    Coordinate3d workPlaneCoord = GbmpModelViewUtil::GetWorkPlaneCoordinate(pModelView);
    OwnerPtr<IGraphicsCurve3d> opCurve0 = pLine0->GetCurve();
    OwnerPtr<IGraphicsCurve3d> opCurve1 = pLine1->GetCurve();
    OwnerPtr<IGraphicsCurve3d> opCurve2 = pLine2->GetCurve();
    OwnerPtr<IGraphicsCurve3d> opCurve3 = pLine3->GetCurve();
    OwnerPtr<IGraphicsCurve3d> opArc = pArc->GetCurve();
    DBG_WARN_AND_RETURN_VOID_UNLESS(opCurve0 && opCurve1 && opCurve2 && opCurve3 && opArc, L"参照线的几何曲线不存在",L"GDMPLab",L"2024-03-30");
    // 添加共点约束
    FamilyConstraintUtils::AddCoincidentConstraintOutOfSketch(pDoc,
        workPlaneCoord,
        pLine0->GetOwnerElement()->GetBasicInformation()->GetElementId(), FamilyConstraintReferenceType::End, opCurve0->GetId(),
        pLine1->GetOwnerElement()->GetBasicInformation()->GetElementId(), FamilyConstraintReferenceType::Start, opCurve1->GetId());
    FamilyConstraintUtils::AddCoincidentConstraintOutOfSketch(pDoc,
        workPlaneCoord,
        pLine1->GetOwnerElement()->GetBasicInformation()->GetElementId(), FamilyConstraintReferenceType::End, opCurve1->GetId(),
        pLine2->GetOwnerElement()->GetBasicInformation()->GetElementId(), FamilyConstraintReferenceType::Start, opCurve2->GetId());
    FamilyConstraintUtils::AddCoincidentConstraintOutOfSketch(pDoc,
        workPlaneCoord,
        pLine2->GetOwnerElement()->GetBasicInformation()->GetElementId(), FamilyConstraintReferenceType::End, opCurve2->GetId(),
        pLine3->GetOwnerElement()->GetBasicInformation()->GetElementId(), FamilyConstraintReferenceType::Start, opCurve3->GetId());
    FamilyConstraintUtils::AddCoincidentConstraintOutOfSketch(pDoc,
        workPlaneCoord,
        pLine3->GetOwnerElement()->GetBasicInformation()->GetElementId(), FamilyConstraintReferenceType::End, opCurve3->GetId(),
        pLine0->GetOwnerElement()->GetBasicInformation()->GetElementId(), FamilyConstraintReferenceType::Start, opCurve0->GetId());
    FamilyConstraintUtils::AddCoincidentConstraintOutOfSketch(pDoc,
        workPlaneCoord,
        pLine0->GetOwnerElement()->GetBasicInformation()->GetElementId(), FamilyConstraintReferenceType::End, opCurve0->GetId(),
        pArc->GetOwnerElement()->GetBasicInformation()->GetElementId(), FamilyConstraintReferenceType::Start, opArc->GetId());
    FamilyConstraintUtils::AddCoincidentConstraintOutOfSketch(pDoc,
        workPlaneCoord,
        pArc->GetOwnerElement()->GetBasicInformation()->GetElementId(), FamilyConstraintReferenceType::End, opArc->GetId(),
        pLine3->GetOwnerElement()->GetBasicInformation()->GetElementId(), FamilyConstraintReferenceType::Start, opCurve3->GetId());

    newRefLines.push_back(pLine0);
    newRefLines.push_back(pLine1);
    newRefLines.push_back(pLine2);
    newRefLines.push_back(pLine3);
    newRefLines.push_back(pArc);
}

void gfam::FamMEPTemplateUtility::InitTransitionFamilyDocument(gcmp::IDocument* pDoc)
{
    IFamilyManager* pFamilyManager = IFamilyManager::Get(pDoc);
    DBG_WARN_AND_RETURN_VOID_UNLESS(pFamilyManager != nullptr, L"pFamilyManager为空",L"GDMPLab",L"2024-03-30");
    pFamilyManager->GetBasicInformation()->SetName(MEP_TRANSITION_TEMPLATE_NAME);

    //////////////////////////////////////////////////////////////////////////
    // 族参数
    // L"偏移宽度"
    const double width = 300;
    std::wstring strWidthName = GBMP_TR(L"偏移宽度");
    IFamilyParameterDefinition* pWidthParam = AddFamilyParameter(pFamilyManager, strWidthName, width, UNIT(Length), false, L"");
    DBG_WARN_AND_RETURN_VOID_UNLESS(pWidthParam, L"创建“偏移宽度”参数不成功",L"GDMPLab",L"2024-03-30");

    // L"偏移高度"
    const double height = 300;
    IFamilyParameterDefinition* pHeightParam = AddFamilyParameter(pFamilyManager, GBMP_TR(L"偏移高度"), height, UNIT(Length), false, L"");
    DBG_WARN_AND_RETURN_VOID_UNLESS(pHeightParam, L"创建“偏移高度”参数不成功",L"GDMPLab",L"2024-03-30");

    // L"内衬厚度"
    // L"隔热层厚度"
    AddMEPThicknessParameter(pFamilyManager);

    //////////////////////////////////////////////////////////////////////////
    // 参照平面
    std::vector<IReferencePlane *> newRefPlanes;
    CreateTransitionReferencePlane(pDoc, newRefPlanes);

    // 距离约束
    // 前后中心面，左右中心面
    IReferencePlane * pFrontBackCenterPlane = GetReferencePlane(pDoc, ProjectReferenceTypeOfReferencePlane::CenterOfFrontBack);
    IReferencePlane * pTopBottomCenterPlane = GetReferencePlane(pDoc, ProjectReferenceTypeOfReferencePlane::CenterOfTopBottom);
    DBG_WARN_AND_RETURN_VOID_UNLESS(pFrontBackCenterPlane&&pTopBottomCenterPlane, L"获取不到参照平面! ",L"GDMPLab",L"2024-03-30");

    IModelView* pModelView = GbmpModelViewUtil::FindViewByBuiltinIndex(pDoc, BMVI_BaseLevel);
    DBG_WARN_AND_RETURN_VOID_UNLESS(pModelView != nullptr, L"无法获得ModelView",L"GDMPLab",L"2024-03-30");
    Coordinate3d workPlaneCoord = GbmpModelViewUtil::GetWorkPlaneCoordinate(pModelView);
    Vector3d dimPosition(-2800, 0, 0);
    IFamilyMultiDistanceDimension* pDim = nullptr;
    IFamilyDistanceConstraint* pDistanceConstraint0 = FamStructureTemplateUtility::CreateDistanceConstraint(pDoc, dimPosition, FamilyTemplateConst::DimScale
        , workPlaneCoord, pFrontBackCenterPlane->GetBasicInformation()->GetElementId(), gcmp::GraphicsNodeReferenceType::GraphicsNodeSelf, gcmp::GraphicsNodeId(1)
        , newRefPlanes.at(0)->GetBasicInformation()->GetElementId(), gcmp::GraphicsNodeReferenceType::GraphicsNodeSelf, gcmp::GraphicsNodeId(1), pDim);
    DBG_WARN_AND_RETURN_VOID_UNLESS(pDistanceConstraint0, L"距离约束创建失败! ",L"GDMPLab",L"2024-03-30");
    pDistanceConstraint0->CalcDimValue();

    Coordinate3d coord(Vector3d::Zero, Vector3d::UnitX, Vector3d::UnitZ);
    IFamilyDistanceConstraint* pDistanceConstraint1 = FamStructureTemplateUtility::CreateDistanceConstraint(pDoc, dimPosition, FamilyTemplateConst::DimScale
        , coord, pTopBottomCenterPlane->GetBasicInformation()->GetElementId(), gcmp::GraphicsNodeReferenceType::GraphicsNodeSelf, gcmp::GraphicsNodeId(1)
        , newRefPlanes.at(1)->GetBasicInformation()->GetElementId(), gcmp::GraphicsNodeReferenceType::GraphicsNodeSelf, gcmp::GraphicsNodeId(1), pDim);
    DBG_WARN_AND_RETURN_VOID_UNLESS(pDistanceConstraint1, L"距离约束创建失败! ",L"GDMPLab",L"2024-03-30");
    pDistanceConstraint1->CalcDimValue();

    FamilySolverResult ret = FamilySolverUtils::SolveDocument(pDoc);
    DBG_WARN_AND_RETURN_VOID_UNLESS(ret == FamilySolverResult::Ok, L"解算失败! ",L"GDMPLab",L"2024-03-30");
}

//                |
//                |
// _______________|________ 0
// _______________|________ 1
//                | 
// _______________|________ 2
// _______________|________ 3
//                |
//                |
//                | 5
//
// ________________________ 4
void FamMEPTemplateUtility::CreateTransitionReferencePlane(gcmp::IDocument* pDoc, std::vector<gcmp::IReferencePlane *>& newRefPlanes)
{
    auto CreateReferencePlane = [&](const Vector3d& startPt, const Vector3d& endPt, const Vector3d& dir)->IReferencePlane *
    {
        IReferencePlane * pPlane = ReferencePlaneUtils::CreateByPoints(pDoc, startPt, endPt, dir);
        DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pPlane != nullptr, L"创建参照平面失败",L"GDMPLab",L"2024-03-30");
        pPlane->GetBasicInformation()->SetName(GBMP_TR(L"参照平面"));
        return pPlane;
    };
    const double lengthU = 4500;
    const double lengthV0 = 3600;
    const double lengthV1 = 3000;

    // 平面视图下
    Vector3d startPtZ(-lengthU*0.5, 300, 0);
    Vector3d endPtZ(lengthU*0.5, 300, 0);
    IReferencePlane * pLevelPlane0 = CreateReferencePlane(startPtZ, endPtZ, Vector3d::UnitZ);
    pLevelPlane0->SetVisibleUVMin(Vector2d(-lengthU*0.5, -lengthV1*0.5));
    pLevelPlane0->SetVisibleUVMax(Vector2d(lengthU*0.5, lengthV1*0.5));

    startPtZ = Vector3d(-lengthU*0.5, 150, 0);
    endPtZ = Vector3d(lengthU*0.5, 150, 0);
    IReferencePlane * pLevelPlane1 = CreateReferencePlane(startPtZ, endPtZ, Vector3d::UnitZ);
    pLevelPlane1->SetVisibleUVMin(Vector2d(-lengthU*0.5, -lengthV0*0.5));
    pLevelPlane1->SetVisibleUVMax(Vector2d(lengthU*0.5, lengthV0*0.5));

    startPtZ = Vector3d(-lengthU*0.5, -150, 0);
    endPtZ = Vector3d(lengthU*0.5, -150, 0);
    IReferencePlane * pLevelPlane2 = CreateReferencePlane(startPtZ, endPtZ, Vector3d::UnitZ);
    pLevelPlane2->SetVisibleUVMin(Vector2d(-lengthU*0.5, -lengthV0*0.5));
    pLevelPlane2->SetVisibleUVMax(Vector2d(lengthU*0.5, lengthV0*0.5));

    startPtZ = Vector3d(-lengthU*0.5, -300, 0);
    endPtZ = Vector3d(lengthU*0.5, -300, 0);
    IReferencePlane * pLevelPlane3 = CreateReferencePlane(startPtZ, endPtZ, Vector3d::UnitZ);
    pLevelPlane3->SetVisibleUVMin(Vector2d(-lengthU*0.5, -lengthV1*0.5));
    pLevelPlane3->SetVisibleUVMax(Vector2d(lengthU*0.5, lengthV1*0.5));

    startPtZ = Vector3d(-lengthU*0.5, -3000, 0);
    endPtZ = Vector3d(lengthU*0.5, -3000, 0);
    IReferencePlane * pLevelPlane4 = CreateReferencePlane(startPtZ, endPtZ, Vector3d::UnitZ);
    pLevelPlane4->SetVisibleUVMin(Vector2d(-lengthU*0.5, -lengthU*0.5));
    pLevelPlane4->SetVisibleUVMax(Vector2d(lengthU*0.5, lengthU*0.5));
    newRefPlanes.push_back(pLevelPlane4);

    startPtZ = Vector3d(300, -lengthV0*0.5, 0);
    endPtZ = Vector3d(300, lengthV0*0.5, 0);
    IReferencePlane * pLevelPlane5 = CreateReferencePlane(startPtZ, endPtZ, Vector3d::UnitZ);
    pLevelPlane5->SetVisibleUVMin(Vector2d(-lengthV0*0.5, -lengthU*0.5));
    pLevelPlane5->SetVisibleUVMax(Vector2d(lengthV0*0.5, lengthU*0.5));

    // 右视图下
    startPtZ = Vector3d(0, -lengthU*0.5, 300);
    endPtZ = Vector3d(0, lengthU*0.5, 300);
    IReferencePlane * pRightPlane0 = CreateReferencePlane(startPtZ, endPtZ, Vector3d::UnitX);
    pRightPlane0->SetVisibleUVMin(Vector2d(-lengthV1*0.5, -lengthU*0.5));
    pRightPlane0->SetVisibleUVMax(Vector2d(lengthV1*0.5, lengthU*0.5));

    startPtZ = Vector3d(0, -lengthU*0.5, 150);
    endPtZ = Vector3d(0, lengthU*0.5, 150);
    IReferencePlane * pRightPlane1 = CreateReferencePlane(startPtZ, endPtZ, Vector3d::UnitX);
    pRightPlane1->SetVisibleUVMin(Vector2d(-lengthV0*0.5, -lengthU*0.5));
    pRightPlane1->SetVisibleUVMax(Vector2d(lengthV0*0.5, lengthU*0.5));

    startPtZ = Vector3d(0, -lengthU*0.5, -150);
    endPtZ = Vector3d(0, lengthU*0.5, -150);
    IReferencePlane * pRightPlane2 = CreateReferencePlane(startPtZ, endPtZ, Vector3d::UnitX);
    pRightPlane2->SetVisibleUVMin(Vector2d(-lengthV0*0.5, -lengthU*0.5));
    pRightPlane2->SetVisibleUVMax(Vector2d(lengthV0*0.5, lengthU*0.5));

    startPtZ = Vector3d(0, -lengthU*0.5, -300);
    endPtZ = Vector3d(0, lengthU*0.5, -300);
    IReferencePlane * pRightPlane3 = CreateReferencePlane(startPtZ, endPtZ, Vector3d::UnitX);
    pRightPlane3->SetVisibleUVMin(Vector2d(-lengthV1*0.5, -lengthU*0.5));
    pRightPlane3->SetVisibleUVMax(Vector2d(lengthV1*0.5, lengthU*0.5));

    startPtZ = Vector3d(0, -lengthU*0.5, -3000);
    endPtZ = Vector3d(0, lengthU*0.5, -3000);
    IReferencePlane * pRightPlane4 = CreateReferencePlane(startPtZ, endPtZ, Vector3d::UnitX);
    pRightPlane4->SetVisibleUVMin(Vector2d(-lengthU*0.5, -lengthU*0.5));
    pRightPlane4->SetVisibleUVMax(Vector2d(lengthU*0.5, lengthU*0.5));
    newRefPlanes.push_back(pRightPlane4);

    // 与前后中心重合的参照面
    startPtZ = Vector3d(lengthU*0.5, 0, 0);
    endPtZ = Vector3d(-lengthU*0.5, 0, 0);
    IReferencePlane * pPlane0 = ReferencePlaneUtils::CreateByPoints(pDoc, startPtZ, endPtZ, Vector3d::UnitZ);
    DBG_WARN_AND_RETURN_VOID_UNLESS(pPlane0 != nullptr, L"创建参照平面失败",L"GDMPLab",L"2024-03-30");
    pPlane0->GetBasicInformation()->SetName(GBMP_TR(L"另一端宽度中心面"));

    // 与上下中心重合的参照面
    startPtZ = Vector3d(lengthU*0.5, 0, 0);
    endPtZ = Vector3d(-lengthU*0.5, 0, 0);
    IReferencePlane * pPlane1 = ReferencePlaneUtils::CreateByPoints(pDoc, startPtZ, endPtZ, Vector3d::UnitY);
    DBG_WARN_AND_RETURN_VOID_UNLESS(pPlane1 != nullptr, L"创建参照平面失败",L"GDMPLab",L"2024-03-30");
    pPlane1->GetBasicInformation()->SetName(GBMP_TR(L"另一端高度中心面"));
}

IFamilyParameterDefinition* gfam::FamMEPTemplateUtility::AddFamilyParameter(gfam::IFamilyManager* pFM,
    const std::wstring& strParamName,
    double dValue,
    const gcmp::UniIdentity& utId,
    bool bFormula,
    const std::wstring& strFormula)
{
    ParameterStorageType pst = ParameterStorageType::Double;

    FamilyParameterType fpt = FamilyParameterType::Length;
    UniIdentity ptId = PARAMETER_TYPE(Length);
    if (utId == UNIT(Length))
    {
        fpt = FamilyParameterType::Length;
        ptId = PARAMETER_TYPE(Length);
    }
    else if (utId == UNIT(Angle))
    {
        fpt = FamilyParameterType::Angle;
        ptId = PARAMETER_TYPE(Angle);
    }
    else
    {
        DBG_WARN_AND_RETURN_NULLPTR_UNLESS(false, L"该类型参数暂时未定义! ",L"GDMPLab",L"2024-03-30");
    }


    IFamilyParameterDefinition* pParamDef = IFamilyParameterDefinition::Create(pFM->GetDocument(), strParamName, fpt, true, L"");

    pFM->AddFamilyParameterDefinition(pParamDef);

    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pParamDef, L"参数添加不成功! ",L"GDMPLab",L"2024-03-30");
    pFM->SetFamilyParameterProcessType(pParamDef, ParameterProcessType::GeneralInput);

    if (bFormula)
    {

        pFM->UpdateFamilyParameterDefinition(pParamDef, strFormula);
        pFM->SetFamilyParameterProcessType(pParamDef, ParameterProcessType::GeneralOutput);
        
    }
    
    pFM->SetParameterValueStorage(pParamDef, TransferOwnership(IParameterValueDouble::Create(dValue)));
    return pParamDef;
}

void FamMEPTemplateUtility::AddMEPThicknessParameter(gfam::IFamilyManager* pFM)
{
    // L"内衬厚度"
    std::wstring strLiningThickness = GBMP_TR(L"内衬厚度");
    const double liningThickness = 0;
    IFamilyParameterDefinition* pLiningThicknessParam = AddFamilyParameter(pFM, strLiningThickness, liningThickness, UNIT(Length), false, L"");
    DBG_WARN_AND_RETURN_VOID_UNLESS(pLiningThicknessParam, L"创建“内衬厚度”参数不成功",L"GDMPLab",L"2024-03-30");

    // L"隔热层厚度"
    std::wstring strInsulatorThickness = GBMP_TR(L"隔热层厚度");
    const double insulatorThickness = 0;
    IFamilyParameterDefinition* pInsulatorThicknessParam = AddFamilyParameter(pFM, strInsulatorThickness, insulatorThickness, UNIT(Length), false, L"");
    DBG_WARN_AND_RETURN_VOID_UNLESS(pInsulatorThicknessParam, L"创建“隔热层厚度”参数不成功",L"GDMPLab",L"2024-03-30");
}

IReferencePlane * FamMEPTemplateUtility::GetReferencePlane(gcmp::IDocument* pDoc, ProjectReferenceTypeOfReferencePlane refPlaneType)
{
    std::vector<IElement*> allRefPlanes = pDoc->GetElementsByCategory(BuiltInCategoryUniIdentities::BICU_REFERENCE_PLANE);
    for (auto& planeElement : allRefPlanes)
    {
        IReferencePlane * pPlane = quick_cast<IReferencePlane>(planeElement);
        DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pPlane, L"其他非参照平面对象使用了BIC_REFERENCE_PLANE! ",L"GDMPLab",L"2024-03-30");
        if (pPlane->GetProjectReferenceType() == refPlaneType)
        {
            return pPlane;
        }
    }

    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(false, L"获取不到参照平面! ",L"GDMPLab",L"2024-03-30");
}

